import { message, Popconfirm, Spin, Tree } from 'antd';
import React, { forwardRef, useImperativeHandle, useCallback, useState, useEffect } from 'react';
import { isEmpty, uniq } from 'lodash';
import request from '@/utils/request';
import styles from './index.less';
import IconButton from '@/components/IconButton';
import useProcessCatalogTree from '@/hooks/UseProcessCatalogTree';

const { TreeNode } = Tree;

export function findParentKeysRecursive(children, allNodes) {
  const parentKeys = [];
  children.forEach(child => {
    const parents = allNodes.filter(node => node.key === child.parentKey);
    parentKeys.push(...parents.map(parent => parent.key));
    parentKeys.push(...findParentKeysRecursive(parents, allNodes));
  });
  return uniq(parentKeys);
}

function CatalogTree(
  { searchKey, onDelete, onEditDir, onEditProcess, onAddSubDir, onSelectProcess, onSelectDir },
  ref
) {
  // 删除目录
  const deleteDir = useCallback(
    node => {
      const hide = message.loading('目录删除中，请稍等...', 0);
      request
        .post(`/process/deleteCatalog?catalogId=${node.catalogId}`)
        .then(() => {
          onDelete();
          message.success('目录删除成功');
        })
        .finally(hide);
    },
    [onDelete]
  );

  // 删除流程
  const deleteProcess = useCallback(
    node => {
      const hide = message.loading('流程删除中，请稍等...', 0);
      request
        .post(`/process/deleteProcess?processCode=${node.processCode}`)
        .then(() => {
          onDelete();
          message.success('流程删除成功');
        })
        .finally(hide);
    },
    [onDelete]
  );

  // 渲染标题
  const renderTitle = useCallback(
    (node, keyword) => {
      const isDir = !node.leaf;
      const isProcess = !isDir;
      const hasChildren = node.children && node.children.length > 0;

      keyword = keyword || '';
      const index = node.title.indexOf(keyword);
      const beforeStr = node.title.substr(0, index);
      const afterStr = node.title.substr(index + keyword.length);

      const title =
        index > -1 ? (
          <span>
            {beforeStr}
            <span style={{ color: '#f50' }}>{keyword}</span>
            {afterStr}
          </span>
        ) : (
          <span>{node.title}</span>
        );

      return (
        <span className={styles.tree_node}>
          <span className={styles.tree_node_title}>
            {title}
            {!node.leaf && (
              <span style={{ marginLeft: 3, color: '#67d6ac' }}>({node.childCount})</span>
            )}
          </span>
          <span className={styles.tree_node_icons}>
            <IconButton
              onClick={() => (isDir ? onEditDir(node) : onEditProcess(node))}
              icon="edit"
              title="编辑"
            />
            {isDir ? (
              <IconButton onClick={() => onAddSubDir(node)} icon="plus-circle" title="新增" />
            ) : null}
            {isDir && !hasChildren ? (
              <Popconfirm
                title={`确定要删除目录【${node.title}】吗`}
                onConfirm={() => deleteDir(node)}
              >
                <IconButton icon="delete" title="删除" />
              </Popconfirm>
            ) : null}
            {isProcess ? (
              <Popconfirm
                title={`确定要删除流程【${node.title}】吗`}
                onConfirm={() => deleteProcess(node)}
              >
                <IconButton icon="delete" title="删除" />
              </Popconfirm>
            ) : null}
          </span>
        </span>
      );
    },
    [deleteDir, deleteProcess, onAddSubDir, onEditDir]
  );

  const { renderTree, loading: treeLoading, refresh, flattenData } = useProcessCatalogTree({
    renderTitle,
  });

  useImperativeHandle(ref, () => ({
    refresh,
  }));

  // 选择树节点
  const handleSelectNode = useCallback(
    (keys, e) => {
      const node = e.node.props.dataRef;
      if (!node) {
        onSelectDir('-1');
        return;
      }
      if (e.selected) {
        if (node.leaf) {
          onSelectProcess(node.processId);
        } else {
          onSelectDir(node.catalogId);
        }
      } else {
        onSelectDir('-1');
      }
    },
    [onSelectDir, onSelectProcess]
  );

  const [expandedKeys, setExpandedKeys] = useState([]);

  useEffect(() => {
    if (!isEmpty(searchKey)) {
      const nodesToSearch = flattenData.filter(node => node.title.includes(searchKey));
      const parentKeys = findParentKeysRecursive(nodesToSearch, flattenData);
      setExpandedKeys(parentKeys);
    }
  }, [flattenData, searchKey]);

  return (
    <Spin spinning={treeLoading}>
      <Tree
        showIcon
        onSelect={handleSelectNode}
        expandedKeys={expandedKeys}
        onExpand={setExpandedKeys}
      >
        <>
          <TreeNode title="全部" key="-1" isLeaf />
          {renderTree(searchKey)}
        </>
      </Tree>
    </Spin>
  );
}

export default forwardRef(CatalogTree);
